package com.engine.salary.wrapper;

import com.api.formmode.mybatis.util.SqlProxyHandle;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.component.WeaTableColumnGroup;
import com.engine.salary.entity.salaryacct.param.SalaryAcctResultQueryParam;
import com.engine.salary.entity.salaryacct.po.SalaryAcctRecordPO;
import com.engine.salary.entity.salaryitem.param.SalaryItemSearchParam;
import com.engine.salary.entity.salaryitem.po.SalaryItemPO;
import com.engine.salary.entity.salarysob.bo.SalarySobItemAggregateBO;
import com.engine.salary.entity.salarysob.dto.SalaryApprovalDTO;
import com.engine.salary.entity.salarysob.dto.SalarySobEmpFieldDTO;
import com.engine.salary.entity.salarysob.param.ApprovalRequestSaveParam;
import com.engine.salary.entity.salarysob.param.SalaryApprovalQueryParam;
import com.engine.salary.entity.salarysob.po.SalarySobEmpFieldPO;
import com.engine.salary.enums.salaryaccounting.LockStatusEnum;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.mapper.sys.SalarySysConfMapper;
import com.engine.salary.service.*;
import com.engine.salary.service.impl.*;
import com.engine.salary.sys.entity.po.SalarySysConfPO;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.page.PageInfo;
import com.engine.salary.util.page.SalaryPageUtil;
import com.engine.salary.util.valid.ValidUtil;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import weaver.hrm.User;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.engine.salary.sys.constant.SalarySysConstant.SALARY_ACCT_FIXED_COLUMNS;

/**
 * 薪资账套的薪资审批
 * <p>Copyright: Copyright (c) 2024</p>
 * <p>Company: 泛微软件</p>
 *
 * @author qiantao
 * @version 1.0
 **/
public class SalaryApprovalWrapper extends Service {

    private SalaryApprovalRuleService getSalaryApprovalRuleService(User user) {
        return ServiceUtil.getService(SalaryApprovalRuleServiceImpl.class, user);
    }

    private SalaryAcctRecordService getSalaryAcctRecordService(User user) {
        return ServiceUtil.getService(SalaryAcctRecordServiceImpl.class, user);
    }

    private SalaryAcctResultService getSalaryAcctResultService(User user) {
        return ServiceUtil.getService(SalaryAcctResultServiceImpl.class, user);
    }

    private SalarySobEmpFieldService getSalarySobEmpFieldService(User user) {
        return ServiceUtil.getService(SalarySobEmpFieldServiceImpl.class, user);
    }

    private SalaryItemService getSalaryItemService(User user) {
        return ServiceUtil.getService(SalaryItemServiceImpl.class, user);
    }
    private SalaryAcctExcelService getSalaryAcctExcelService(User user) {
        return (SalaryAcctExcelService) ServiceUtil.getService(SalaryAcctExcelServiceImpl.class, user);
    }

    private SalarySysConfMapper getSalarySysConfMapper() {
        return SqlProxyHandle.getProxy(SalarySysConfMapper.class);
    }

    /**
     * 薪资账套的薪资审批规则
     *
     * @param queryParam 查询参数
     * @return
     */
    public SalaryApprovalDTO salaryApprovalForm(SalaryApprovalQueryParam queryParam) {
        ValidUtil.doValidator(queryParam);
        return getSalaryApprovalRuleService(user).salaryApprovalForm(queryParam);
    }

    /**
     * 保存薪资账套的薪资审批规则
     *
     * @param salaryApprovalDTO
     *
     */
    public void saveSalaryApprovalForm(SalaryApprovalDTO salaryApprovalDTO) {
        getSalaryApprovalRuleService(user).saveSalaryApprovalForm(salaryApprovalDTO);
    }

    public List<SalaryItemPO> listSalaryApprovalItem(SalaryItemSearchParam queryParam) {
        return getSalaryApprovalRuleService(user).listSalaryApprovalItem(queryParam);
    }

    public SalaryApprovalDTO getApprovalInfoByRecordId(Long salaryAcctRecordId) {
        return getSalaryApprovalRuleService(user).getApprovalInfoByRecordId(salaryAcctRecordId);
    }

    public Map<String, Object> listSalaryApprovalAcctResult(SalaryAcctResultQueryParam queryParam) {
        ValidUtil.doValidator(queryParam);
        // 审批信息
        SalaryApprovalDTO approvalInfoByRecordId = getSalaryApprovalRuleService(user).getApprovalInfoByRecordId(queryParam.getSalaryAcctRecordId());

        // 查询薪资核算记录
        SalaryAcctRecordPO salaryAcctRecordPO = getSalaryAcctRecordService(user).getById(queryParam.getSalaryAcctRecordId());
        if (Objects.isNull(salaryAcctRecordPO)) {
            throw new SalaryRunTimeException(SalaryI18nUtil.getI18nLabel(98747, "薪资核算记录不存在或已被删除"));
        }

        // 查询薪资核算结果（分页）
        PageInfo<Map<String, Object>> page = getSalaryAcctResultService(user).listPageByParam(queryParam);

        // 构建薪资核算结果审批列表的表头
        List<WeaTableColumnGroup> columns = Lists.newArrayList();
        // 查询薪资账套的员工信息字段
        List<SalarySobEmpFieldPO> salarySobEmpFieldPOS = getSalarySobEmpFieldService(user).listBySalarySobId(salaryAcctRecordPO.getSalarySobId());
        List<SalarySobEmpFieldDTO> salarySobEmpFieldDTOS = new SalarySobItemAggregateBO().buildEmpField(salarySobEmpFieldPOS);
        // 获取薪资项目信息
        List<SalaryItemPO> salaryItemPOS = getSalaryItemService(user).listAll();
        Map<Long, Integer> salaryItemWidthMap = SalaryEntityUtil.convert2Map(salaryItemPOS, SalaryItemPO::getId, SalaryItemPO::getWidth);
        // 员工信息字段
        for (SalarySobEmpFieldDTO salarySobEmpFieldDTO : salarySobEmpFieldDTOS) {
            columns.add(new WeaTableColumnGroup(SalaryPageUtil.selfAdaption(salarySobEmpFieldDTO.getFieldName(), 0), salarySobEmpFieldDTO.getFieldName(), salarySobEmpFieldDTO.getFieldId()));
        }
        // 薪资项目分组下的薪资项目
        for (SalaryApprovalDTO.approvalItemGroup groupDTO : approvalInfoByRecordId.getApprovalItemGroup()) {
            if (CollectionUtils.isEmpty(groupDTO.getApprovalItems())) {
                continue;
            }
            List<WeaTableColumnGroup> childrenColumns = Lists.newArrayList();
            for (SalaryApprovalDTO.approvalItem approvalItemDTO : groupDTO.getApprovalItems()) {
                childrenColumns.add(new WeaTableColumnGroup(SalaryPageUtil.selfAdaption(approvalItemDTO.getSalaryItemName(), salaryItemWidthMap.getOrDefault(approvalItemDTO.getSalaryItemId(), 0) == null ? 0 : salaryItemWidthMap.getOrDefault(approvalItemDTO.getSalaryItemId(), 0)), approvalItemDTO.getSalaryItemName(), "" + approvalItemDTO.getSalaryItemId(), LockStatusEnum.UNLOCK.getValue().toString()));
            }
            WeaTableColumnGroup weaTableColumnWapper = new WeaTableColumnGroup(SalaryPageUtil.selfAdaption(groupDTO.getGroupName(), 0), groupDTO.getGroupName(), groupDTO.getGroupName(), childrenColumns);
            columns.add(weaTableColumnWapper);
        }

        // 获取固定列头数
        SalarySysConfPO salaryAcctFixedColumns = getSalarySysConfMapper().getOneByCode(SALARY_ACCT_FIXED_COLUMNS);
        if (salaryAcctFixedColumns != null) {
            int fixedNum = NumberUtils.isCreatable(salaryAcctFixedColumns.getConfValue()) ? Integer.valueOf(salaryAcctFixedColumns.getConfValue()) : 3;
            if (fixedNum == 0) {
                fixedNum = 3;
            }
            for (int i = 0; i < fixedNum; i++) {
                columns.get(i).setFixed("left");
            }
        }

        Map<String, Object> datas = new HashMap<>();
        datas.put("pageInfo", page);
        datas.put("columns", columns);

        return datas;
    }

    /**
     * 保存审批流程id
     * @param saveParam
     */
    public void saveApprovalRequestId(ApprovalRequestSaveParam saveParam) {
        getSalaryApprovalRuleService(user).saveApprovalRequestId(saveParam);
    }

    public Map<String, Object> sumSalaryApprovalAcctResult(SalaryAcctResultQueryParam queryParam) {
        ValidUtil.doValidator(queryParam);
        Map<String, Object> datas = new HashMap<>();

        Map<String, Object> sumRow = getSalaryApprovalRuleService(user).sumRow(queryParam);
        datas.put("sumRow", sumRow);
        return datas;
    }

    public XSSFWorkbook exportSalaryApprovalAcctResult(SalaryAcctResultQueryParam param) {
        return getSalaryAcctExcelService(user).exportSalaryApprovalAcctResult(param);
    }
}
